package cate.game.role.res.kingsacrifice;

import cate.common.table.d.GDHero;
import cate.common.table.d.GDPrivilege;
import cate.common.table.throne.sacrifice.KingSacrificeItemRow;
import cate.common.table.throne.sacrifice.KingSacrificeLevelRow;
import cate.common.table.throne.sacrifice.KingSacrificeRefreshRow;
import cate.common.util.GameResult;
import cate.game.res.MixRes;
import cate.game.res.MixResAdder;
import cate.game.res.MixResItem;
import cate.game.role.Role;
import cate.game.role.RoleDependent;
import cate.game.role.res.kingsacrifice.msg.KingSacrificeJobUpdate;
import cate.game.role.res.kingsacrifice.msg.KingSacrificeResp;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@NoteClass("灵王祭祀数据")
public class RoleKingSacrifice extends RoleDependent {

	@NoteField("当前赛季")
	public int season;

	@NoteField(value = "职业数据",detail = "只记录有操作的职业")
	public Map<Byte, KingSacrificeJobInfo> jobs;

	@Override
	public void initialize(Role role) {
		super.initialize(role);
		if (jobs == null) {
			jobs = new HashMap<>();
		}
		jobs.values().forEach(KingSacrificeJobInfo::initialize);
	}

	@Override
	public void onEnter() {
		checkSeason(true);
	}

	public void checkSeason(boolean silence) {
		int curSeason = role.getGame().pvp.gradePvp.status.season;
		if (season == curSeason) {
			return;
		}
		season = curSeason;
		jobs.clear();
		if (!silence) {
			noticeUpdate();
		}
	}

	private KingSacrificeJobInfo getJob(byte job) {
		if (!GDHero.Job.valid(job)) {
			return null;
		}
		KingSacrificeJobInfo jobInfo = jobs.get(job);
		if (jobInfo == null) {
			jobInfo = new KingSacrificeJobInfo(job);
			jobInfo.initialize();
			jobs.put(job, jobInfo);
		}
		return jobInfo;
	}

	@Override
	public void onDaySpan(boolean silence){
		jobs.values().forEach(KingSacrificeJobInfo::onDaySpan);
		if(!silence){
			noticeUpdate();
		}
	}

	public EcResult<Void> buy(int id) {
		EcResult<Void> r = new EcResult<>();
		KingSacrificeItemRow itemRow = role.getGame().table.kingSacrifice.item.get(id);
		if (itemRow == null) {
			return r.fail("商品不存在");
		}
		KingSacrificeJobInfo jobInfo = getJob(itemRow.job);
		if (jobInfo == null) {
			return r.fail("职业有误");
		}
		KingSacrificeJobInfo.Item item = jobInfo.getItem(itemRow.itemId);
		if (item.buy) {
			return r.fail("商品已售罄");
		}
		GameResult<MixResItem>  cr = new MixRes(itemRow.getCost(hasPrivilege())).consume(role);
		if(!cr.ok()){
			return r.fail(cr.message);
		}
		item.buy = true;
		new MixResAdder().setRes(new MixRes(itemRow.rwdStr)).setDialogReward(true).exe(role);
		addExp(jobInfo, itemRow.exp);
		role.sendNow(new KingSacrificeJobUpdate(jobInfo));
		return r.success();
	}

	private void addExp(KingSacrificeJobInfo jobInfo, int addExp) {
		jobInfo.exp += addExp;
		KingSacrificeLevelRow levelRow = role.getGame().table.kingSacrifice.level.findRow(jobInfo.job, jobInfo.level);
		while (levelRow != null && levelRow.exp > 0 && jobInfo.exp >= levelRow.exp) {
			jobInfo.exp -= levelRow.exp;
			jobInfo.level++;
			levelRow = role.getGame().table.kingSacrifice.level.findRow(jobInfo.job, jobInfo.level);
		}
	}

	private KingSacrificeRefreshRow getRefreshRow(){
		return role.getGame().table.kingSacrifice.refresh.getFirst();
	}

	public EcResult<Void> refresh(byte job) {
		EcResult<Void> r = new EcResult<>();
		KingSacrificeJobInfo jobInfo = getJob(job);
		if (jobInfo == null) {
			return r.fail("职业有误");
		}
		if (!jobInfo.buyAnyItem()) {
			return r.fail("尚未购买任何商品 无法刷新");
		}
		if (freeLeft(jobInfo) > 0) {
			jobInfo.free++;
		} else if (payLeft(jobInfo) > 0) {
			GameResult<MixResItem> cr = new MixRes(getRefreshRow().refreshCost).consume(role);
			if (!cr.ok()) {
				return r.fail(cr.message);
			}
			jobInfo.pay++;
		} else {
			return r.fail("刷新次数不足");
		}
		jobInfo.items.clear();
		role.sendNow(new KingSacrificeJobUpdate(jobInfo));
		return r.success();
	}

	public EcResult<Void> batchBuy(byte job) {
		EcResult<Void> r = new EcResult<>();
		if (!hasPrivilege()) {
			return r.fail("尚未激活特权");
		}
		KingSacrificeJobInfo jobInfo = getJob(job);
		if (jobInfo == null) {
			return r.fail("职业有误");
		}
		MixRes totalRwd = new MixRes();
		MixRes totalCost = new MixRes();

		final int freeLeft = freeLeft(jobInfo);
		final int payLeft = payLeft(jobInfo);
		int addExp = 0;

		//刷新消耗
		if (payLeft > 0) {
			totalCost.addList(new MixRes(getRefreshRow().refreshCost).multiply(payLeft));
		}
		List<KingSacrificeItemRow> itemRows = role.getGame().table.kingSacrifice.item.getItemsByJob(job);
		for (KingSacrificeItemRow itemRow : itemRows) {
			KingSacrificeJobInfo.Item item = jobInfo.getItem(itemRow.itemId);
			int buyNum = 0;
			if (!item.buy) {
				buyNum++;
			}
			buyNum += freeLeft;
			buyNum += payLeft;
			if (buyNum > 0) {
				addExp += itemRow.exp * buyNum;
				totalCost.addList(new MixRes(itemRow.getCost(true)).copy().multiply(buyNum));
				totalRwd.addList(new MixRes(itemRow.rwdStr).copy().multiply(buyNum));
			}
		}
		GameResult<MixResItem> cr = totalCost.consume(role);
		if (!cr.ok()) {
			return r.fail(cr.message);
		}
		jobInfo.free += freeLeft;
		jobInfo.pay += payLeft;
		addExp(jobInfo, addExp);
		jobInfo.items.values().forEach(item -> item.buy = true);


		new MixResAdder().setRes(totalRwd).setDialogReward(true).exe(role);
		role.sendNow(new KingSacrificeJobUpdate(jobInfo));
		return r.success();
	}

	private int freeLeft(KingSacrificeJobInfo jobInfo) {
		return Math.max(0, getRefreshRow().getTotalFree(hasPrivilege()) - jobInfo.free);
	}

	private int payLeft(KingSacrificeJobInfo jobInfo) {
		return Math.max(0, getRefreshRow().getTotalPay(hasPrivilege()) - jobInfo.pay);
	}

	private boolean hasPrivilege(){
		return role.getPay().tradeMall.privilegeMall.checkValied(GDPrivilege.Type.KING_SACRIFICE);
	}

	public void noticeUpdate(){
		role.sendNow(new KingSacrificeResp(role));
	}
}
